package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.core.domain.AjaxResult;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.framework.config.IotClientConfig;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.vo.DeviceDetailVo;
import com.zzyl.nursing.vo.ProductVo;
import org.aspectj.weaver.loadtime.Aj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 设备Service业务层处理
 *
 * @author zhangshiyu
 * @date 2025-09-22
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {
    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 查询设备
     *
     * @param id 设备主键
     * @return 设备
     */
    @Override
    public Device selectDeviceById(Long id) {
        return deviceMapper.selectById(id);
    }

    /**
     * 查询设备列表
     *
     * @param device 设备
     * @return 设备
     */
    @Override
    public List<Device> selectDeviceList(Device device) {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 新增设备
     *
     * @param device 设备
     * @return 结果
     */
    @Override
    public int insertDevice(Device device) {
        return deviceMapper.insert(device);
    }

    /**
     * 修改设备
     *
     * @param device 设备
     * @return 结果
     */
    @Override
    public int updateDevice(Device device) {
        return deviceMapper.updateById(device);
    }

    /**
     * 批量删除设备
     *
     * @param ids 需要删除的设备主键
     * @return 结果
     */
    @Override
    public int deleteDeviceByIds(Long[] ids) {
        return deviceMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除设备信息
     *
     * @param id 设备主键
     * @return 结果
     */
    @Override
    public int deleteDeviceById(Long id) {
        return deviceMapper.deleteById(id);
    }

    @Autowired
    private IoTDAClient client;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void syncProductList() {
        ListProductsRequest request = new ListProductsRequest();
        request.setLimit(50);
        ListProductsResponse listProductsResponse = client.listProducts(request);
        List<ProductSummary> products = listProductsResponse.getProducts();

        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_LIST_KEY, JSONUtil.toJsonStr(products));

    }

    @Override
    public List<ProductVo> allProduct() {
        String s = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_LIST_KEY);
        if (StrUtil.isBlank(s)) {
            return null;
        }


        List<ProductVo> list = JSONUtil.toList(s, ProductVo.class);
        return list;
    }

    //    @Autowired
//    private IoTDAClient client;
    @Override
    public void register(DeviceDto dto) {
        if (dto.getPhysicalLocationType() == null) {
            dto.setPhysicalLocationType(-1);
        }
        //设备名称是否重复
        //select * from device where device_name =?
        Long count = lambdaQuery()
                .eq(Device::getDeviceName, dto.getDeviceName())
                .count();
        if (count != null && count > 0) {
            throw new RuntimeException("设备名重复了");
        }
        //设备标识是否重复
        //select count(*) from device where node_id = ?
        Long count1 = lambdaQuery()
                .eq(Device::getNodeId, dto.getNodeId())
                .count();
        if (count1 != null && count1 > 0) {
            throw new RuntimeException("设备标识重复了");
        }
        //同一位置是否绑定了相同的产品
        Long count2 = lambdaQuery()
                .eq(Device::getBindingLocation, dto.getBindingLocation())
                .eq(Device::getLocationType, dto.getLocationType())
                .eq(Device::getPhysicalLocationType, dto.getPhysicalLocationType())
                .eq(Device::getProductKey, dto.getProductKey())
                .count();
        if (count2 != null && count2 > 0) {
            throw new RuntimeException("同一位置绑定了相同的产品");
        }

        //注册设备
        //本意是想先在后端数据库中添加，但是由于缺少字段，需要从华为云中获取，所以要先在华为云注册
        AddDeviceRequest request = new AddDeviceRequest();
        AddDevice addDevice = new AddDevice();
        addDevice.setNodeId(dto.getNodeId());
        addDevice.setProductId(dto.getProductKey());
        addDevice.setDeviceName(dto.getDeviceName());
        AuthInfo authInfo = new AuthInfo();
        String secret = IdUtil.fastSimpleUUID();
        authInfo.setSecret(secret);
        addDevice.setAuthInfo(authInfo);
        request.setBody(addDevice);
        AddDeviceResponse response = null;
        try {
            response = client.addDevice(request);
            if (response == null) {
                throw new RuntimeException("响应结果是null");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String deviceId = response.getDeviceId();
        Device bean = BeanUtil.toBean(dto, Device.class);
        bean.setIotId(deviceId);
        bean.setSecret(secret);
        bean.setHaveEntranceGuard(0);


        //本地保存
        save(bean);
    }

    @Override
    public DeviceDetailVo getDeviceDetailVo(String iotId) {
        Device device = lambdaQuery()
                .eq(Device::getIotId, iotId)
                .one();

        //去华为云找两个字段
        ShowDeviceRequest request = new ShowDeviceRequest();
        request.withDeviceId(device.getIotId());

        ShowDeviceResponse response = client.showDevice(request);
        String status = response.getStatus();
        String activeTime = response.getActiveTime();
        DeviceDetailVo deviceDetailVo = BeanUtil.toBean(device, DeviceDetailVo.class);
        deviceDetailVo.setDeviceStatus(status);
        System.out.println("activeTime ========== " + activeTime);
        //如果激活了有激活时间，再去设置激活时间
        if (activeTime != null) {
//            deviceDetailVo.setActiveTime(activeTime);
            // 解析原始时间字符串为ZonedDateTime
            ZonedDateTime utcTime = ZonedDateTime.parse(activeTime);

            // 转换为东八区时间
            ZonedDateTime chinaTime = utcTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));

            deviceDetailVo.setActiveTime(chinaTime.toLocalDateTime());
        }
        return deviceDetailVo;
    }

    @Override
    public AjaxResult queryServiceProperties(String iotId) {
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.withDeviceId(iotId);
        ShowDeviceShadowResponse response = client.showDeviceShadow(request);

        System.out.println("response = " + JSONUtil.toJsonStr(response));

        DeviceShadowProperties reported = response.getShadow().get(0).getReported();
        String eventTime = reported.getEventTime();
        System.out.println("eventTime = " + eventTime);
        // 解析为UTC时间
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
        LocalDateTime utcLocalDateTime = LocalDateTime.parse(eventTime, inputFormatter);
        ZonedDateTime utcZonedDateTime = utcLocalDateTime.atZone(ZoneOffset.UTC);

        // 转换为东八区时间
        ZonedDateTime beijingTime = utcZonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));

        // 格式化输出
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String result = beijingTime.format(outputFormatter);

        System.out.println(result); // 输出：2025-09-23 02:03:51

        LinkedHashMap<String, Object> properties = (LinkedHashMap<String, Object>) reported.getProperties();
        List<Map<String, Object>> list = new ArrayList<>();
        properties.forEach((k, v) -> {
            HashMap<String, Object> map = new HashMap<>();
            map.put("functionId", k);
            map.put("value", v);
            map.put("eventTime", result);
            list.add(map);
        });

//        System.out.println(response.toString());
        return AjaxResult.success(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateDivce(Device device) {
        //先在后端修改，再去华为云修改
        Device dbDevice = getById(device.getId());
        if (dbDevice == null) {
            throw new RuntimeException("这个设备在数据库中没有找到，没法更新");
        }

        //如果是随身设备，物理位置设为-1
        if (device.getLocationType() == 0) {
            device.setPhysicalLocationType(-1);
        }
        //数据库中更新设备信息
        try {
            updateById(device);
        } catch (Exception e) {
            throw new RuntimeException("后端数据库更新设备失败");
        }
        //更新华为云
        UpdateDeviceRequest request = new UpdateDeviceRequest();
        request.setDeviceId(device.getIotId());

        UpdateDevice body = new UpdateDevice();
        body.setDeviceName(device.getDeviceName());
        request.withBody(body);

        UpdateDeviceResponse response = client.updateDevice(request);

        return "修改设备成功";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String deleteDevice(String iotId) {
        //后台删除设备
//        //先查到设备，后面华为云上传需要用到
//
//        Device device = lambdaQuery()
//                .eq(Device::getIotId, iotId)
//                .one();
        //delete from device where id = ?
        try {
            remove(new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotId));
        } catch (Exception e) {
            throw new RuntimeException("后台删除设备失败:" + e);
        }


        //华为云删除设备
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.withDeviceId(iotId + "");

        DeleteDeviceResponse response = client.deleteDevice(request);

        return "删除设备成功";
    }

    @Override
    public AjaxResult queryProduct(String productId) {
        ShowProductRequest request = new ShowProductRequest();
        request.withProductId(productId);
        ShowProductResponse response = client.showProduct(request);
        List<ServiceCapability> serviceCapabilities = response.getServiceCapabilities();
        return AjaxResult.success(serviceCapabilities);
    }
}
